/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gamecomponents.skeletontesthelper;

import java.util.HashMap;
/**
 *
 * @author Szokodi, Urbán
 */
public abstract class Assistant
{
/****************************** VÁLTOZÓK ******************************/
    
    static HashMap<String,Integer> quantityOfThisObject = new HashMap<String, Integer>(); //az adott objektum száma
    static String name = new String(); //objektum neve
    static int tab = 0; //behúzás intenzitása
    static HashMap<Object,String> objectsName = new HashMap<Object,String>(); //objektumok neve
    static StringBuffer sb = new StringBuffer(); //Ide írjuk a kimenetet
    
/****************************** METÓDUSOK ******************************/
    private static void writeMessage(Interaction inter, Object obj, String methodName, Parameter[] params){
        for (int i=0; i<tab; i++) sb.append(" "); //behúzás
        switch(inter){
            case CRT:
                sb.append("CRT:");
                break;
            case CALL:
                sb.append("CALL:");
                break;
            case RET:
                sb.append("RET:");
                break;
            default: ;
        }
        if(inter!=Interaction.RET)
            sb.append(
                objectsName
                    .get(obj)).append(
            ".").append(
            methodName).append(
            "("    
            );//kiírás
        for(int i=0; i<params.length;i++){
            if(params[i].isReferenceType()==false)    //Ha nem referenciatípus,
                sb.append("[").append(params[i].getType()).append("]").append(   //akkor kiírunk róla mindent
                        params[i].getName()).append("=").append(params[i].getValue());
            else
                if(params[i].isNull()==true)      //Ha null, akkor egy null-t írunk ki
                    sb.append("null");
                else
                    sb.append(params[i].getName());  //Referenciatípusnál a nevét írjuk ki
            if(i<params.length)
                sb.append(",");
        }
        if(inter!=Interaction.RET)
            sb.append(")");
        sb.append("/n");
    }
    
    public static void setName(String objName) //név beállítása
    {
        name = objName;
    }

    static String getObjectsName(Object obj){
        try {
            String str = objectsName.get(obj);
            if(str == null) throw new NameNotDeterminedException(obj);
                    return str;
        } catch (NameNotDeterminedException ex) {
            System.out.println(ex.getMessage());
            sb.append(ex.getMessage()).append("/n");
            System.exit(0);
        }
        return null;
    }
    
    //konstruktorhívás esetén
    static void onCreate(Object obj, String methodName, Parameter[] params)
            throws NameNotDeterminedException
    {//kivételkezelés
        if (name == null)
            throw new NameNotDeterminedException(obj);
        
        Integer id = quantityOfThisObject
                        .get(
                            obj
                                .getClass()
                                  .getName()
                            );
        //léterhozunk egy id-t, melynek értéke az n-edik objektum
        //ebből a típusból
        if (id == null)
        {
            id = new Integer(0); //ha még nincs ilyen objektum, akkor az id értéke nulla.
            quantityOfThisObject
                .put(
                    obj
                        .getClass()
                            .getName(),
                    id
                    );
            
        }
        //betesszük a map-be a most létrehozott objektumunkat
        objectsName
            .put(
                obj,
                "["+
                obj
                    .getClass()
                        .getSimpleName()+
                "#"+
                id+
                "]"+
                name
                );
        id++; //id-t megnöveljük
        writeMessage(Interaction.CRT, obj, methodName, params);
    }
    
    
    static void onCall(Object obj, String methodName, Parameter[] params) //metódushívás
    {   
        writeMessage(Interaction.CALL, obj,methodName,params);        
        tab++; //behúzás megnövelése
    }
    
    static void onRet(Object obj, String methodName, Parameter[] params) //visszatérés esetén fut le
    {
        tab--; //behúzás csökkentése
        
        writeMessage(Interaction.RET,obj,methodName,params);
    }

    public static void write(Interaction inter, Object obj, String methodName, Parameter[] params)
    {
      try //hibakezelés
          {
            switch (inter) {
                 case CRT :
                    onCreate(obj, methodName, params);
                     break;
                
                 case CALL: onCall(obj, methodName, params);
                     break;
                
                 case RET :
                     if(params.length>1) throw new TooManyParametersOnReturnException(obj);
                     onRet(obj, methodName, params);
                     break;
                
                 default  : ;
                     break;
            }
        }
        catch (Exception ex)
        {
            System.out.println(ex.getMessage()); //hiba kiírása
            sb.append(ex.getMessage()).append("/n");
            System.exit(0);
        }           
    }
    public static void writeToConsole(){
          System.out.println(sb);
      }
}